﻿#include "global.h"
#include "PinLexer.h"

#include <QByteArray>
#include <QList>
#include <QHash>
#include <QTextCodec>

#ifdef PIN_MEM_REF
int newTimes = 0;
int freeTimes = 0;
void newTime(int v)
{
    newTimes += v;
}
void subTime()
{
    ++freeTimes;
}
#endif

#ifdef WIN32
#include <windows.h> // 包含 Windows API 头文件
#endif

extern QByteArray s_srcUtf8Bytes;

extern antlr4::CommonTokenStream* tokensListen;

//调用函数的参数栈
QList<ExprValue*>* s_callFunStack = nullptr;

#ifdef NDD_PIN_FUN
#else
//为了避免路径中\\不一样导致的查找不到问题，进行统一替换
QString getRegularFilePath(QString& path)
{
#ifdef _WIN32
    path = path.replace("/", "\\");
#else
    path = path.replace("\\", "/");
#endif

    return path;
}
#endif

void initFunCallStack()
{
    if(s_callFunStack == nullptr)
    {
        s_callFunStack = new QList<ExprValue*>();
			#ifdef PIN_MEM_REF
            newTime();
#endif
    }
}

//入栈顺序，参数-参数-函数名称
QList<ExprValue*>* getFunCallStack()
{
    return s_callFunStack;
}

void destoryFunCallStack()
{
    if(s_callFunStack != nullptr)
    {
        delete s_callFunStack;
#ifdef PIN_MEM_REF
        freeTimes++;
#endif
        s_callFunStack = nullptr;
    }
}


//把原始的词法中的字符串值，转换为按转义后的值。
QByteArray lexBytesToEscapeBytes(QByteArray& src)
{
	QByteArray dst;
	dst.reserve(src.size());

	//src 必然是"xxx" 格式。丢掉前后的""
	for (int i = 1, s = src.size()-1; i < s; ++i)
	{
		//当前是\,下一个还有字符
		char c = src.at(i);

		if (c == '\\' && (i+1) < s)
		{
			char next = src.at(i + 1);

			switch (next)
			{
			case 't':
				dst.append('\t');
				++i;
				break;
			case 'r':
				dst.append('\r');
				++i;
				break;
			case 'n':
				dst.append('\n');
				++i;
				break;
			case 'b':
				dst.append('\b');
				++i;
				break;
				//不要\f，发现打印出来乱码。
			//case 'f':
			//	dst.append('\f');
			//	++i;
			//	break;
            case '"':
                dst.append('\"');
                ++i;
                break;
            case '\'':
                dst.append('\'');
                ++i;
                break;
            case '\\':
                dst.append('\\');
                ++i;
                break;
			default:
				dst.append('\\');
				break;
			}
		}
		else
		{
			dst.append(c);
		}
	}
	return dst;
}

//把原始的词法中的裸字符串值，转换为按转义后的值。
//三种格式：1） R"( )" 2) r"" 3) r''
QByteArray lexRawBytesToEscapeBytes(QByteArray& src)
{
	//直接转换即可，去掉前面的头尾。-5是前面3 R"(个，后面2个字符")，都要去掉。
	//原始字符串是 R"(XXX)"的格式，保留XXX中的内容即可。
    if (src.startsWith('R'))
    {
	QByteArray dst(src.data() + 3, src.size()-5);
	return dst;
}
    else
    {
        //去掉前面的r" 和后面"即可。
        QByteArray dst(src.data() + 2, src.size() - 3);
        return dst;
    }
}

//根据变量名判断变量类型。已经失效了。现在是只判断类型名称。
//
int getVarTypeByName(std::string& name)
{
    int ret = EXPR_ERR;
    const char* rawPtr = name.data();

    int code = (rawPtr[0] << 8) | (rawPtr[1]);

	switch (code)
	{
	case ('z' << 8 | 's'):
        return EXPR_INT;
	case ('c' << 8 | 'z'):
        return EXPR_INT64;
	case ('x' << 8 | 's'):
        return EXPR_FLOAT;

	case ('z' << 8 | 'f'):
        //进一步检查是zf还是zfc
        return (name.size() == 3 && rawPtr[2] == 'c')?EXPR_STRING:EXPR_CHAR;

    case ('b' << 8 | 'l'):
        return EXPR_BOOL;
   /* case ('j' << 8 | 'g'):
    case ('J' << 8 | 'G'):
        return EXPR_STRUCT;*/
    case ('l' << 8 | 'b'):
        return EXPR_LIST;
    case ('z' << 8 | 'd'):
        return EXPR_MAP;
    case ('w' << 8 | 'j'):
        return EXPR_FILE;
    case ('s' << 8 | 'j'):
        return EXPR_DATE;
    case ('h' << 8 | 's'):
    case ('h' << 8 | 'd'): //回调也是函数
        return EXPR_FUN; //还有细分是不是成员函数
    case ('e' << 8 | 'x'):
        return EXPR_EXCEL;
    case ('p' << 8 | 'i'):
        ret = (name.size() == 3 && rawPtr[2] == 'n')?EXPR_PIN:EXPR_ERR;
        break;
    case ('k' << 8 | 'z'):
        ret = (name.size() == 3 && rawPtr[2] == 'f') ? EXPR_WCHAR : EXPR_ERR;
        break;
    case ('n' << 8 | 'd'):
        ret = (name.size() == 3 && rawPtr[2] == 'd')?EXPR_NDD:EXPR_ERR;
        break;
    case ('s' << 8 | 't'):
        ret = (name == "string") ? EXPR_U16STRING : EXPR_ERR;
        break;

	default:
		break;
	}

    //啥也不是，检查是不是结构体。
    if(ret == EXPR_ERR && isStructDescExist(name))
    {
        ret = EXPR_STRUCT;
}

    return ret;
}

QString getVarTypeNameByName(std::string& name, antlr4::ParserRuleContext* ctx)
{
    if (name.empty())
    {
        return "";
    }
    //先判断是不是全局类型值。
    if (isKeyWordTypeVar(name))
    {
        //如果是全局的包调用，比如zfc/pin/excel等,是不会有变量的。
        return QString(u8"包名或 %1 类型").arg(QStr(name));
    }

    //具体获得是什么结构
    SymNode* pSym = getVarFromSymTable(name,ctx);

    if(pSym != nullptr && pSym->type == EXPR_STRUCT)
    {
        STRUCT_VALUE_DATA* pStValue = (STRUCT_VALUE_DATA*)(pSym->value.vpoint);

        std::string stTypeName = pStValue->structType;


        return QString(u8"结构类型 %1").arg(QStr(stTypeName));
    }
    else if(pSym != nullptr && pSym->type == EXPR_STRUCT_DEC)
    {
        //STRUCT_VALUE_DATA* pStValue = (STRUCT_VALUE_DATA*)(pSym->value.vpoint);

        //std::string stTypeName = pStValue->structType;


        return QString(u8"结构描述类型 %1").arg(QStr(pSym->name));
    }

    return getExpeTypeValue(pSym->type);

}


QString getExpeTypeValue(int type,ExprValue *pExpr)
{
    switch (type)
    {
    case EXPR_INT:
        return u8"整数类型";

    case EXPR_INT64:
        return u8"长整数类型";

    case EXPR_FLOAT:
        return u8"小数类型";

    case EXPR_STRING:
        return  u8"字符串类型";

    case EXPR_U16STRING:
        return  u8"U16字符串类型";

    case EXPR_CHAR:
        return  u8"字符类型";

    case EXPR_WCHAR:
        return  u8"U16 宽字符类型";

    case EXPR_BOOL:
        return u8"逻辑bool类型";

    case EXPR_STRUCT:
    {
        if(pExpr != nullptr)
        {
            STRUCT_VALUE_DATA* pStValue = (STRUCT_VALUE_DATA*)(pExpr->value.vpoint);

            std::string stTypeName = pStValue->structType;


            return QString(u8"结构类型 %1").arg(QStr(stTypeName));
        }

        return u8"结构类型";
    }

    case EXPR_STRUCT_DEC:
    {
        return u8"结构描述类型";
    }
    case EXPR_LIST:
        return u8"列表类型";

    case EXPR_MAP:
        return u8"字典类型";

    case EXPR_FILE:
        return u8"文件类型";

    case EXPR_DATE:
        return u8"时间类型";

    case EXPR_FUN:
    case EXPR_MEMFUN:
        return u8"函数类型";

    case EXPR_EXCEL:
        return u8"Excel 表格类型";

    case EXPR_PIN:
        return u8"Pin 包类型";

    case EXPR_GLOBAL_PACKNAME:
    {
        if(pExpr != nullptr)
        {
            return getExpeTypeValue(pExpr->value.vpacktype) + u8"全局包类型";
        }
        return u8"全局包类型";
    }

    default:
        break;
    }
    return u8"未知类型";
}

std::string getTypeDescName(int type,ExprValue *pExpr)
{
    switch (type)
    {
    case EXPR_INT:
        return "zs";

    case EXPR_INT64:
        return "czs";

    case EXPR_FLOAT:
        return "xs";

    case EXPR_STRING:
        return  "zfc";

    case EXPR_U16STRING:
        return  "string";

    case EXPR_CHAR:
        return  "zf";

    case EXPR_WCHAR:
        return  "kzf";

    case EXPR_BOOL:
        return "bl";

    case EXPR_STRUCT:
    {
        return "jiegou";
    }
    case EXPR_LIST:
        return "lb";

    case EXPR_MAP:
        return "zd";

    case EXPR_FILE:
        return "wj";

    case EXPR_DATE:
        return "sj";

    case EXPR_FUN:
    case EXPR_MEMFUN:
        return "hs";

    case EXPR_EXCEL:
        return "excel";

    case EXPR_STRUCT_DEC:
        return "jiegou_desc";

    case EXPR_GLOBAL_PACKNAME:
        if(pExpr != nullptr)
        {
            return "package:" + getTypeDescName(pExpr->value.vpacktype);
        }
        return "global_package";//全局包类型。

    default:
        break;
    }
    return "error-type";
}

//全局的符号表。每个函数，每个作用域，每个变量定义，都放在上面
static QList<SymNode*>* s_sysNode = nullptr;
static std::unordered_map<std::string, SymNode*> *s_globalVarSysNode = nullptr; // 全局变量的符号表

//结构名称和其对应id分配的表
static std::unordered_map<std::string, int> *s_structDescIdMap = nullptr; // 结构类型名称和id对应的表。

//只有底部cpp对外暴露的结构，才有这个对应的id, 自己写的结构，没有该id，统一为-1
void initStructDescIdMap()
{
    if(s_structDescIdMap == nullptr)
    {
        s_structDescIdMap = new std::unordered_map<std::string, int>();
#ifdef PIN_MEM_REF
        newTime();
#endif
        s_structDescIdMap->insert({"XLWorksheet",XLWorksheet_Struct_ID});
       /* s_structDescIdMap->insert({"PString",PString_Struct_Id});
        s_structDescIdMap->insert({"PChar",PChar_Struct_Id});*/
#ifdef NDD_PIN_FUN
        s_structDescIdMap->insert({ "PNddMain",NddMainWin_Struct_ID });
        s_structDescIdMap->insert({ "PEdit",Editor_Struct_ID });
#endif
        s_structDescIdMap->insert({ "RegExp", REGEXP_Struct_ID});
        s_structDescIdMap->insert({ "RegMatch",REGMATCH_Struct_ID });
        s_structDescIdMap->insert({ "RegMatchIter",REGMATCH_ITER_Struct_ID });


    }
}

int getStructIdByDescName(std::string& name)
{
    std::unordered_map<std::string, int>::iterator it = s_structDescIdMap->find(name);
    if (it != s_structDescIdMap->end())
    {
        return it->second;
    }

    return Struct_Unkonwn_ID;
}

void destoryStructDescIdMap()
{
    if(s_structDescIdMap != nullptr)
    {
        s_structDescIdMap->clear();
        delete s_structDescIdMap;
        s_structDescIdMap = nullptr;
#ifdef PIN_MEM_REF
        freeTimes++;
#endif
    }
}


static std::unordered_map<std::string, FUN_SYM_INFO*> * s_funSysNode = nullptr;

//对地址做一个引用计数。
static std::unordered_map<quint64,int>* listOrMapRefNum = nullptr;

void initListMapRefNum()
{
    if(listOrMapRefNum == nullptr)
    {
        listOrMapRefNum = new std::unordered_map<quint64,int>();
		#ifdef PIN_MEM_REF
            newTime();
#endif
    }
}

void destoryListMapRefNum()
{
    if(listOrMapRefNum != nullptr)
    {

        listOrMapRefNum->clear();
        delete listOrMapRefNum;
        listOrMapRefNum = nullptr;
#ifdef PIN_MEM_REF
        freeTimes++;
#endif
    }
}

int getListMapRefNum(void* pAddr)
{
    quint64 ptrValue = reinterpret_cast<quint64>(pAddr);

    std::unordered_map<quint64,int>::iterator it = listOrMapRefNum->find(ptrValue);

    if(it != listOrMapRefNum->end())
    {
        return it->second;
    }

    //不存在也返回0，表示没有
    //QString msg = QString(u8"没有对列表或字典的引用计数，发生严重错误！");
    //AbortException(msg);
    return 0;
}

//加入计数，没有则增加
int addListMapRefNum(void* pAddr)
{
    quint64 ptrValue = reinterpret_cast<quint64>(pAddr);

    std::unordered_map<quint64,int>::iterator it = listOrMapRefNum->find(ptrValue);

    if(it != listOrMapRefNum->end())
    {
        return ++(it->second);
    }
    else
    {
        //不存在加入
        listOrMapRefNum->operator [](ptrValue) = 1;
    }

    return 1;
}


int addListMapRefNum(SymNode* pExpr)
{

    switch (pExpr->type)
    {
        case EXPR_LIST:
        case EXPR_MAP:
        case EXPR_FILE:
        case EXPR_EXCEL:
        {
            if (pExpr->value.vpoint != nullptr)
            {
                return addListMapRefNum(pExpr->value.vpoint);
            }
        }
        break;
    }

    return 0;
}

int addListMapRefNum(ExprValue& pExpr)
{
    switch (pExpr.type)
    {
    case EXPR_LIST:
    case EXPR_MAP:
    case EXPR_FILE:
    case EXPR_EXCEL:
    {
        if (pExpr.value.vpoint != nullptr)
        {
            return addListMapRefNum(pExpr.value.vpoint);
        }
    }
    break;
    }

    return 0;
}

int subListMapRefNum(ExprValue& pExpr)
{
    switch (pExpr.type)
    {
    case EXPR_LIST:
    case EXPR_MAP:
    case EXPR_FILE:
    case EXPR_EXCEL:
    {
        if (pExpr.value.vpoint != nullptr)
        {
            return subListMapRefNum(pExpr.value.vpoint);
        }
    }
    break;
    }

    return 0;
}


//减少计算，为0则删除
int subListMapRefNum(void* pAddr)
{
    quint64 ptrValue = reinterpret_cast<quint64>(pAddr);

    std::unordered_map<quint64,int>::iterator it = listOrMapRefNum->find(ptrValue);

    int ret = 0;

    if(it != listOrMapRefNum->end())
    {
        ret = --(it->second);

        //为0 则自动删除，外部没有引用了
        if(it->second == 0)
        {
            listOrMapRefNum->erase(it);
        }

        return ret;
    }
    return ret;
}


int subListMapRefNum(SymNode* pExpr)
{
    switch (pExpr->type)
    {
    case EXPR_LIST:
    case EXPR_MAP:
    case EXPR_FILE:
    case EXPR_EXCEL:
    {
        if (pExpr->value.vpoint != nullptr)
        {
            return subListMapRefNum(pExpr->value.vpoint);
        }
    }
    break;
    }

    return 0;
}

QList<SymNode*>* getPinSymTable()
{
	if (s_sysNode == nullptr)
	{
        s_sysNode = new QList<SymNode*>();
		#ifdef PIN_MEM_REF
            newTime();
#endif
	}
	return s_sysNode;
}

void destoryPinSymTable()
{
    if (s_sysNode != nullptr)
    {
        for(QList<SymNode*>::iterator it = s_sysNode->begin(); it != s_sysNode->end(); ++it)
        {
            (*it)->destory();
            delete (*it);
#ifdef PIN_MEM_REF
            freeTimes++;
#endif
        }
        delete s_sysNode;
        s_sysNode = nullptr;
#ifdef PIN_MEM_REF
        freeTimes++;
#endif
    }
}

void insertGlobalSymTable(std::string& name, SymNode* pSym)
{
    s_globalVarSysNode->insert({name,pSym});
}

bool isGlobalSymExist(std::string &name)
{
    return s_globalVarSysNode->find(name) != s_globalVarSysNode->end();
}

//是不是结构体的类型申明
bool isStructDescExist(const std::string &name)
{
    auto it = s_globalVarSysNode->find(name);

    if(it != s_globalVarSysNode->end())
    {
        return it->second->type == EXPR_STRUCT_DEC;
    }
    return false;
}

void initVarGlobalSymTable()
{
    if(nullptr == s_globalVarSysNode)
    {
        s_globalVarSysNode = new std::unordered_map<std::string, SymNode*>();
#ifdef PIN_MEM_REF
        newTime();
#endif
    }
}
void destoryVarGlobalSymTable()
{
    if(nullptr != s_globalVarSysNode)
    {

        for(std::unordered_map<std::string, SymNode*>::iterator it = s_globalVarSysNode->begin(); it != s_globalVarSysNode->end(); ++it)
        {
            it->second->destory();
            delete it->second;
#ifdef PIN_MEM_REF
            freeTimes++;
#endif
        }
        s_globalVarSysNode->clear();
        delete s_globalVarSysNode;
        s_globalVarSysNode = nullptr;
#ifdef PIN_MEM_REF
        freeTimes++;
#endif
    }
}
//查找全局变量的符号表
SymNode* getVarFromGlobalSymTable(std::string name, antlr4::ParserRuleContext *ctx, int isStruct)
{

    std::unordered_map<std::string, SymNode*>::iterator it = s_globalVarSysNode->find(name);
    if (it != s_globalVarSysNode->end())
    {
        return it->second;
    }
    else
    {
        //错误，没有遇到作用域
        QString errmsg;

        if(isStruct == 0)
        {
            if (ctx != nullptr)
            {
                //如果语句中有%，会导致变量打印不出来，所以先打印变量，只是一个特例。
                errmsg = QString(u8"错误：行号 %1 找不到变量 %2，语句 %3 变量没有定义或者不在作用域！").arg(curLine).arg(QStr(name)).arg(curStatement);
            }
            else
            {
                errmsg = QString(u8"错误：行号 %1 找不到变量 %2，变量没有定义或者不在作用域！").arg(getCurFunQSName()).arg(QStr(name));

            }
        }
        else
        {
            if (ctx != nullptr)
            {

                antlr4::misc::Interval interval = ctx->getSourceInterval();

                // 从 TokenStream 提取文本
                std::string srcCode = tokensListen->getText(interval);

                //如果语句中有%，会导致变量打印不出来，所以先打印变量，只是一个特例。
                errmsg = QString(u8"错误：行号 %1 找不到结构体类型 %2，语句 %3 结构体没有定义！类型 %2 不是基本类型关键字或结构体名称，是不是写错？").arg(curLine).arg(QStr(name)).arg(QStr(srcCode));
                AbortException(errmsg);
            }
            else
            {
                errmsg = QString(u8"错误：行号 %1 找不到结构体 %2，结构体没有定义！").arg(getCurFunQSName()).arg(QStr(name));
                //这里暂时不退出，让回到上面继续退出。因为这里没有行号。
            }
        }
        //std::exception_ptr eptr = std::make_exception_ptr(std::runtime_error(errmsg.toStdString()));

        //std::rethrow_exception(eptr);


    }


    return nullptr;
}


//找到变量的符号。从栈顶开始找到第一个匹配的。但是不能超过最近的函数作用域。
//这里是找到函数为止。函数的入参，放在函数和第一个{块的中间。
//第一个块作用域内，不能定义和函数参数同名的参数，和c语言保持一致。
SymNode* getVarFromSymTable(std::string name, antlr4::ParserRuleContext* ctx)
{
    if(s_sysNode == nullptr)
    {
        SymNode* v =  getVarFromGlobalSymTable(name, ctx);

        if (v == nullptr)
        {
            QString errmsg = QString(u8"错误：行号 %1 找不到变量 %2，语句 %3 变量没有定义或者不在当前可见作用域！").arg(curLine).arg(QStr(name)).arg(curStatement);
            AbortException(errmsg);
        }
        return v;
    }
    for (int i = s_sysNode->size() - 1; i >= 0; --i)
    {
        SymNode* v = s_sysNode->at(i);

        if (v->type < VAR_SYM && v->name == name)
        {
            return v;
        }
        //找到根函数了，还是没有，则说明不是局部变量，而是全局变量
        if(v->type == FUN_SYM)
        {
            //找全局
            v =  getVarFromGlobalSymTable(name, ctx);

            if (v == nullptr)
            {
                QString errmsg = QString(u8"错误：行号 %1 找不到变量 %2，语句 %3 变量没有定义或者不在当前可见作用域！").arg(curLine).arg(QStr(name)).arg(curStatement);
                AbortException(errmsg);
            }
            return v;
        }
    }
    QString errmsg = QString(u8"错误：行号 %1 找不到变量 %2，语句 %3 变量没有定义或者不在当前可见作用域！").arg(curLine).arg(QStr(name)).arg(curStatement);
    AbortException(errmsg);

    return nullptr;
}

//是不是关键字类型，比如sj,lb,zd,wj 这几个特定字符。
bool isKeyWordTypeVar(std::string name)
{
    if (name.size() < 2)
    {
        return false;
    }
    const char* rawPtr = name.data();

    int code = (rawPtr[0] << 8) | (rawPtr[1]);

    switch (code)
    {
    case ('z' << 8 | 's'):
    case ('x' << 8 | 's'):
    case ('b' << 8 | 'l'):
    case ('l' << 8 | 'b'):
    case ('z' << 8 | 'd'):
    case ('w' << 8 | 'j'):
    case ('s' << 8 | 'j'):
    case ('h' << 8 | 's'):
    case ('i' << 8 | 'n'): //in
    case ('o' << 8 | 'r'): //or
        return name.size() == 2; //还有细分是不是成员函数
    case ('z' << 8 | 'f'): //zf 或 zfc
        return (name.size() == 2 || ((name.size() == 3) && rawPtr[2] == 'c'));
    case ('p' << 8 | 'i'): //pin的内部命令。
        return (name.size() == 3) && rawPtr[2] == 'n';
    case ('e' << 8 | 'x'): 
        return (name == std::string("excel"));
    case ('c' << 8 | 'z'):
        return (name.size() == 3) && rawPtr[2] == 's';
    case ('n' << 8 | 'd'):
        return (name.size() == 3) && rawPtr[2] == 'd';
    case ('d' << 8 | 'y'):
        return (name.size() == 2 || ((name.size() == 3) && rawPtr[2] == 'h'));
    case ('s' << 8 | 't'):
        return name == std::string("string") || name == std::string("struct");
    case ('k' << 8 | 'z'):
        return  (name.size() == 3) && rawPtr[2] == 'f';
    case ('a' << 8 | 'n'): //and
        return ((name.size() == 3) && rawPtr[2] == 'd');
    case ('n' << 8 | 'o'): //not
        return ((name.size() == 3) && rawPtr[2] == 't');
    case ('f' << 8 | 'o'): //for
        return ((name.size() == 3) && rawPtr[2] == 'r');
    case ('x' << 8 | 'u'): //xun
        return ((name.size() == 3) && rawPtr[2] == 'n');
    case ('w' << 8 | 'h'): //while
        return name == std::string("while");
    case ('p' << 8 | 'a'): //pass
        return (name == std::string("pass"));
    default:
        break;
    }

    return false;
}

std::unordered_map<std::string, FUN_SYM_INFO*>* getPinFunSysTable()
{
	if (s_funSysNode == nullptr)
	{
        s_funSysNode = new std::unordered_map<std::string, FUN_SYM_INFO*>();
		#ifdef PIN_MEM_REF
            newTime();
#endif
	}
	return s_funSysNode;
}

void destoryPinFunSysTable()
{
    if (s_funSysNode != nullptr)
    {
        for(std::unordered_map<std::string, FUN_SYM_INFO*>::iterator it = s_funSysNode->begin(); it != s_funSysNode->end(); ++it)
        {
            it->second->destory();
            delete it->second;
#ifdef PIN_MEM_REF
            freeTimes++;
#endif
        }
        delete s_funSysNode;
        s_funSysNode = nullptr;
#ifdef PIN_MEM_REF
        freeTimes++;
#endif
    }
}


FUN_SYM_INFO* findFunBlock(std::string name)
{
	if (s_funSysNode != nullptr)
	{
        std::unordered_map<std::string, FUN_SYM_INFO*>::iterator it = s_funSysNode->find(name);
		if (it != s_funSysNode->end())
		{
            return it->second;
		}
        else if(name == "quanju_dingyi")
        {
            //如果是quanju_dingyi查找失败，则再查找global
            it = s_funSysNode->find("global");
            if (it != s_funSysNode->end())
            {
                return it->second;
	}
        }
	}


	return nullptr;
}

//函数体，还有函数参数，也需要保存。
FUN_SYM_INFO* addFunBlock(std::string name, std::string& block, std::vector<std::string>& paraList, std::vector<std::string>& retList)
{
    std::unordered_map<std::string, FUN_SYM_INFO*>* pFun = getPinFunSysTable();

    FUN_SYM_INFO* v = new FUN_SYM_INFO();
	#ifdef PIN_MEM_REF
            newTime();
#endif
    v->funBlock = new std::string(block);
#ifdef PIN_MEM_REF
            newTime();
#endif
    if (paraList.size() > 0)
    {
        v->paraList = new std::vector<std::string>(paraList);
		#ifdef PIN_MEM_REF
            newTime();
#endif
    }
    if(retList.size() > 0)
    {
        v->retList = new std::vector<std::string>(retList);
		#ifdef PIN_MEM_REF
            newTime();
#endif
    }

    pFun->insert({name, v});

    return v;
}


void printStackInfo()
{
#ifdef WIN32
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    // 恢复默认颜色（前景色为白色，背景色为黑色）
     SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
#endif

	if (s_sysNode != nullptr)
	{
        std::cout << u8"\n>>>> 调用堆栈如下 : \n\n";
        int lastFunStartLineNum = 0;

        int stackIndex = 0;

        QStringList stackContens;

        /*
        int lastErrorOffsetLineNumInFun = 0;

        //先找到最后一个函数的位置
         //获取最后的出错偏移量
        if (getPinRunStatus() == LAST_ERROR_LINE_NUM)
        {
            pin_status_info info = getPinRunStatusData();
            info.status = LAST_ERROR_LINE_NUM;
            lastErrorOffsetLineNumInFun = info.data;
        }*/

        /*int lastFunStackIndex = 0;

        for (int i = s_sysNode->size() - 1; i >= 0; --i)
        {
            SymNode* v = s_sysNode->at(i);

            if (v->type == FUN_SYM)
            {
                lastFunStackIndex = i;
                break;
            }
        }*/

        QList<QByteArray> srcLines = s_srcUtf8Bytes.split('\n');

        std::string callFunName;

        bool isLastIsCallBackFun = false;

        for (int i = 0, s = s_sysNode->size(); i < s; ++i)
        {
            SymNode* v = s_sysNode->at(i);

            if (v->type == FUN_SYM)
            {
                QString info;

                FUN_SYM_INFO* pSym = findFunBlock(v->name);
                if (pSym != nullptr)
                {
                    if (stackIndex == 0)
                    {
                        lastFunStartLineNum = pSym->funNameLineNum;     
                        callFunName = pSym->funDec;
                    }
                    else if(!isLastIsCallBackFun)
                    {
                        //如果上一个是回调函数，则不需要加上偏移。因为回调函数执行时的偏移位置，还是其在上个函数中的偏移地址。
                        //错误行号 = 当前在块内的偏移+上次调用的函数块开始值。
                        //lastFunStartLineNum += v->value.v2int.vint2 - 1;

                        //因为hs_rukou是翻译执行，总是在第1行，会导致打印是个错误。直接跳过该信息即可。
                        if (v->name == "hs_rukou")
                        {
                            continue;
                        }

                        lastFunStartLineNum = v->value.v2int.vint2;
                    }

                    //如果是最后一个，还要加上错误偏移量。都不需要加了，现在直接调用函数，不是读取语句后翻译执行。
                    //if (lastFunStackIndex == i)
                    //{
                        //lastFunStartLineNum += lastErrorOffsetLineNumInFun;
                    //}

                    if (stackIndex == 0)
                    {
                        info = QString(u8"行号%1 函数入口点 执行语句 %2 ").arg(lastFunStartLineNum).arg(QString(srcLines.at(lastFunStartLineNum - 1)));
                    }
                    else 
                    {
                        //如果上一个是回调函数，则不打印出来。因为回调函数和函数，本质是同一个。
                        //打印回调函数的真实函数的时候，其偏移量是不对的，等于回调函数本身。
                        //if (!isLastIsCallBackFun)
                        {
                            info = QString(u8"行号%1 %2 执行语句 %3").arg(lastFunStartLineNum)
                                .arg(QStr(callFunName)).arg(QString(srcLines.at(lastFunStartLineNum - 1).trimmed()));
                        }
                       /* else
                        {
                            info = QString(u8"函数 %1 执行").arg(QStr(pSym->funDec));
                        }*/
                    }

                    stackContens.push_front(info);


                    lastFunStartLineNum = pSym->funNameLineNum;

                    callFunName = pSym->funDec;
                }
                else
                {
                    std::cout << v->name << std::endl;
                }

                ++stackIndex;
            }
            else if (v->type == HD_TO_HS_INFO)
            {
                int lastCallBackFunOffset = 0;
                size_t pos = v->name.find('@');
                std::string callbackName;

                int funNameLineNum = 0;
                FUN_SYM_INFO* pSym = findFunBlock(*(std::string*)v->value.vpoint);
                if (pSym != nullptr)
                {
                    funNameLineNum = pSym->funNameLineNum;
                }


                if (pos != std::string::npos) {
                    std::string linenum = v->name.substr(0, pos);
                    lastCallBackFunOffset = std::stoi(linenum);
                    callbackName = v->name.substr(pos+1);
                }

                //说明是链式调用，直接使用当前行。链式调用底层cpp，是没有函数代码的，直接视作当前行就是函数开始。
                if (pSym == nullptr)
                {
                    funNameLineNum = lastCallBackFunOffset;
                }

                //错误行号 = 当前在块内的偏移+上次调用的函数块开始值。
                //取消翻译后，直接不需要加了。
                lastFunStartLineNum = lastCallBackFunOffset;

                QString info = QString(u8"行号%1 %2 调用函数 %3 执行函数方式 %4 (行%5) ").arg(lastFunStartLineNum).arg(QStr(callFunName)).arg(QStr(callbackName)).arg(QStr(*(std::string*)v->value.vpoint)).arg(funNameLineNum);
                //std::cout << info.toStdString() << std::endl;

                stackContens.push_front(info);

                if (pSym != nullptr)
                {
                    lastFunStartLineNum = pSym->funNameLineNum;
                }

                callFunName = *(std::string*)(v->value.vpoint);

                //更加回调函数名称，找到详细的函数申明定义。
                pSym = findFunBlock(callFunName);
                if (pSym != nullptr)
                {
                    callFunName = pSym->funDec;  
                }

                isLastIsCallBackFun = true;
            }
            else if (v->type == TIPS_INFO && v->value.vpoint != nullptr)
            {
                QString* info = (QString*)v->value.vpoint;
                stackContens.push_front(*info);
            }
        }

        std::cout << stackContens.join("\n\n").toStdString() << std::endl;
#if 0
        int lastFunStartLineNum = 0;

        int lastErrorOffsetLineNumInFun = 0;

        //获取最后的出错偏移量
        if (getPinRunStatus() == LAST_ERROR_LINE_NUM)
        {
            pin_status_info info = getPinRunStatusData();
            info.status = LAST_ERROR_LINE_NUM;
            lastErrorOffsetLineNumInFun = info.data;
        }
        int stackIndex = 0;

		for (int i = s_sysNode->size() - 1; i >= 0; --i)
		{
            SymNode* v = s_sysNode->at(i);

            if (v->type == FUN_SYM)
			{


                FUN_SYM_INFO* pSym = findFunBlock(v->name);
                if(pSym != nullptr)
                {


                    //最后一个错误的行号，是块号+执行错误的偏移号。
                    if (stackIndex == 0)
                    {
                        lastFunStartLineNum = pSym->blockLineNum + lastErrorOffsetLineNumInFun;
                    }
                    else
                    {
                        lastFunStartLineNum = v->value.v2int.vint2;
                    }

                    QString err = QString(u8"行号%1 %2 函数 %3").arg(lastFunStartLineNum).arg(pSym->funNameLineNum).arg(QStr(pSym->funDec));
                    std::cout << err.toStdString() << std::endl;
                }
                else
                {
                    std::cout << v->name << std::endl;
                }

                ++stackIndex;
			}
            else if (v->type == HD_TO_HS_INFO)
            {
                QString info = QString(u8"      回调函数 %1 调用的函数是 %2 ").arg(QStr(v->name)).arg(QStr(*(std::string *)v->value.vpoint));
                std::cout << info.toStdString() << std::endl;

            }

		}

		std::cout << std::endl;

#endif
	}
}



static QList<pin_status_info> *s_pinRunStatusStack = nullptr;

//获取当前状态。比如定义，当前是在定义变量中
int getPinRunStatus()
{
    if(s_pinRunStatusStack != nullptr && !s_pinRunStatusStack->isEmpty())
    {
        return s_pinRunStatusStack->last().status;
    }
    return PIN_RUN_STATUS::NOTHING_STATUS;
}

pin_status_info getPinRunStatusData()
{
    if (s_pinRunStatusStack != nullptr && !s_pinRunStatusStack->isEmpty())
    {
        return s_pinRunStatusStack->last();
    }
    return pin_status_info();
}


void pushStatus(int v)
{
    if(s_pinRunStatusStack == nullptr)
    {
        s_pinRunStatusStack = new QList<pin_status_info>();
#ifdef PIN_MEM_REF
        newTime();
#endif
    }
    pin_status_info temp;
    temp.status = v;
    s_pinRunStatusStack->append(temp);
}

void pushStatus(pin_status_info& v)
{
    if (s_pinRunStatusStack == nullptr)
    {
        s_pinRunStatusStack = new QList<pin_status_info>();
#ifdef PIN_MEM_REF
        newTime();
#endif
    }
    s_pinRunStatusStack->append(v);
}

void popStatus()
{
    assert(!s_pinRunStatusStack->isEmpty());
    s_pinRunStatusStack->takeLast();
}

void destoryPinRunStatus()
{
    if(s_pinRunStatusStack != nullptr)
    {
        delete s_pinRunStatusStack;
        s_pinRunStatusStack = nullptr;
#ifdef PIN_MEM_REF
        freeTimes++;
#endif
    }
}

//局部变量是否已经存在，在最近的作用域中。只需要检查最近的作用域即可，判断参数是否重复定义。
bool isLoaclVarAlreadyExist(std::string name)
{
    for (int i = s_sysNode->size() - 1; i >= 0; --i)
    {
        SymNode* v = s_sysNode->at(i);

        //已经到第一从作用域，说明没有找到
        if(v->type == SCOPE_SYM)
        {
            return false;
        }
        //如果类型已经存在，则返回
        if (v->type < VAR_SYM && v->name == name)
        {
            return true;
        }
    }
    return false;
}

bool isGloablVarAlreadyExist(std::string name)
{
    auto it = s_globalVarSysNode->find(name);
    return it != s_globalVarSysNode->end();
}

SymNode* getGloablVar(std::string name)
{
    auto it = s_globalVarSysNode->find(name);
    if(it != s_globalVarSysNode->end())
    {
        return it->second;
    }
    return nullptr;
}

//增加一个新作用域，和deleteCurScope匹配
void addNewScope(int type)
{
    SymNode* node = new SymNode;
#ifdef PIN_MEM_REF
    newTime();
#endif
    node->type = type;// 默认是SCOPE_SYM，也可以是for作用域。
    //作用域反而是没有名称的。
    getPinSymTable()->push_back(node);
}

//删除当前作用域，等于是退出当前块
bool deleteCurScope()
{
    for (int i = s_sysNode->size() - 1; i >= 0; --i)
    {
        SymNode* v = s_sysNode->at(i);

        //已经到第一从作用域，删除后返回
        if(v->type == SCOPE_SYM)
        {
            s_sysNode->removeAt(i);
            delete v;
			#ifdef PIN_MEM_REF
        freeTimes++;
#endif
            return true;
        }
        //如果是变量类型,删除，即把当前作用域上建立的临时变量，删除
        if (v->type < VAR_SYM)
        {
            /*if(v->type == EXPR_STRING && v->value.vpoint != nullptr)
            {
                delete v->value.vpoint;
            }*/
            v->destory();
            s_sysNode->removeAt(i);
            delete v;
#ifdef PIN_MEM_REF
        freeTimes++;
#endif
        }
    }

    //错误，没有遇到作用域
    QString errmsg = QString(u8"作用域错误");
    std::exception_ptr eptr = std::make_exception_ptr(std::runtime_error(errmsg.toStdString()));

    std::rethrow_exception(eptr);
    return false;
}


//删除当前循环作用域,退出for的作用域
bool deleteCurForScope()
{
    for (int i = s_sysNode->size() - 1; i >= 0; --i)
    {
        SymNode* v = s_sysNode->at(i);

        //已经到第一从作用域，删除后返回
        if(v->type == FOR_SCOPE)
        {
            s_sysNode->removeAt(i);
            delete v;
			#ifdef PIN_MEM_REF
        freeTimes++;
#endif
            return true;
        }
        //如果是变量类型,删除。把作用域上建立的临时变量，也删除掉。
        if (v->type < VAR_SYM)
        {
            v->destory();
            s_sysNode->removeAt(i);
            delete v;
			#ifdef PIN_MEM_REF
        freeTimes++;
#endif
        }
    }

    //错误，没有遇到作用域
    QString errmsg = QString(u8"循环语句作用域错误");
    std::exception_ptr eptr = std::make_exception_ptr(std::runtime_error(errmsg.toStdString()));

    std::rethrow_exception(eptr);
    return false;
}

//是否在for语句中，需要在for的直接块中，中间不能有其它函数
bool isInFor()
{
    for (int i = s_sysNode->size() - 1; i >= 0; --i)
    {
        SymNode* v = s_sysNode->at(i);

        //先遇到的一个for作用域，成功，说明在for上。
        if(v->type == FOR_SCOPE)
        {
            return true;
        }
        //如果先遇到其它函数作用域，则错误。说明在其它函数作用域中。
        else if (v->type == FUN_SYM)
        {
            return false;
        }
    }
    return false;
}

//删除当前函数，退出函数。函数的形参不需要销毁，因为形参是放在函数第一个根作用域之上一起销毁的。
bool deleteCurFunction()
{
    if(!s_sysNode->isEmpty())
    {
        SymNode* v = s_sysNode->last();

        //已经到第一从作用域，删除后返回
        if (v->type == FUN_SYM)
        {
            s_sysNode->takeLast();
            v->destory();
            delete v;
			#ifdef PIN_MEM_REF
        freeTimes++;
#endif
            return true;
        }
    }

    //错误，没有遇到作用域
    QString errmsg = QString(u8"函数作用域错误");
    std::exception_ptr eptr = std::make_exception_ptr(std::runtime_error(errmsg.toStdString()));

    std::rethrow_exception(eptr);
    return false;
}

//当前调用的函数，是否关注返回值。
bool isFunNeedReturnValue()
{
    for (int i = s_sysNode->size() - 1; i >= 0; --i)
    {
        SymNode* v = s_sysNode->at(i);

        //已经到第一从作用域，
        if(v->type == FUN_SYM)
        {
            return (v->value.vint == NEED_FUN_RET_VALUE);
        }
    }

    QString errmsg = QString(u8"函数调用关系链紊乱");
    std::exception_ptr eptr = std::make_exception_ptr(std::runtime_error(errmsg.toStdString()));

    std::rethrow_exception(eptr);
    return false;
}

//当前函数的返回参数
std::vector<std::string> * curFunRetPara(std::string* funName)
{
    for (int i = s_sysNode->size() - 1; i >= 0; --i)
    {
        SymNode* v = s_sysNode->at(i);

        //已经到第一从作用域，删除后返回
        if(v->type == FUN_SYM)
        {
            FUN_SYM_INFO* info = findFunBlock(v->name);
            if(info != nullptr)
            {
                if (funName != nullptr)
                {
                    *funName = v->name;
                }
                return info->retList;
            }
            break;
        }
    }
    QString errmsg = QString(u8"函数调用关系链紊乱");
    std::exception_ptr eptr = std::make_exception_ptr(std::runtime_error(errmsg.toStdString()));

    std::rethrow_exception(eptr);
    return nullptr;
}

bool setcurFunReturnValue(void* pData)
{
    for (int i = s_sysNode->size() - 1; i >= 0; --i)
    {
        SymNode* v = s_sysNode->at(i);

        //已经到第一从作用域，设置后返回
        if (v->type == FUN_SYM)
        {
            //专门放在函数的返回值上。以前是使用value.vpoint，现在不能使用该值。
            v->funRetValue = pData;
            return true;
        }
    }
    QString errmsg = QString(u8"无法设置函数返回值，函数调用关系链紊乱");
    std::exception_ptr eptr = std::make_exception_ptr(std::runtime_error(errmsg.toStdString()));

    std::rethrow_exception(eptr);
    return false;
}

//取出当前函数的返回值，在函数做表达式调用时需要。
QList<SymNode*>* getcurFunReturnValue()
{
    for (int i = s_sysNode->size() - 1; i >= 0; --i)
    {
        SymNode* v = s_sysNode->at(i);

        //已经到第一从作用域，设置后返回
        if (v->type == FUN_SYM)
        {
            return (QList<SymNode*>*)v->funRetValue;
        }
    }
    //QString errmsg = QString(u8"无法获取函数返回值，函数调用关系链紊乱");
    //AbortException(errmsg);

    return nullptr;
}

std::string getCurFunName()
{
    if (s_sysNode == nullptr)
    {
        return "";
    }
    for (int i = s_sysNode->size() - 1; i >= 0; --i)
    {
        SymNode* v = s_sysNode->at(i);

        //已经到第一从作用域，设置后返回
        if (v->type == FUN_SYM)
        {
            return v->name;
        }
    }
    QString errmsg = QString(u8"无法获取当前函数名，函数调用关系链紊乱");
    std::exception_ptr eptr = std::make_exception_ptr(std::runtime_error(errmsg.toStdString()));

    std::rethrow_exception(eptr);
    return "";
}

SymNode* getCurFunSym()
{
    for (int i = s_sysNode->size() - 1; i >= 0; --i)
    {
        SymNode* v = s_sysNode->at(i);

        //已经到第一从作用域，设置后返回
        if (v->type == FUN_SYM)
        {
            return v;
        }
    }
    QString errmsg = QString(u8"无法获取当前函数名，函数调用关系链紊乱");
    std::exception_ptr eptr = std::make_exception_ptr(std::runtime_error(errmsg.toStdString()));

    std::rethrow_exception(eptr);
    return nullptr;
}

QString getCurFunQSName()
{
    return QString::fromStdString(getCurFunName());
}

#ifdef NDD_PIN_FUN
extern std::atomic<int> threadRet;
#endif

void AbortException(QString& errmsg)
{
#ifdef NDD_PIN_FUN
    //先退出线程
    threadRet = 1;
#endif
    std::exception_ptr eptr = std::make_exception_ptr(std::runtime_error(errmsg.toStdString()));


#ifdef WIN32
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    // 设置文字颜色为红色（前景色为红色，背景色为黑色）
    SetConsoleTextAttribute(hConsole, FOREGROUND_RED);
#endif

    std::rethrow_exception(eptr);

    // 恢复默认颜色（前景色为白色，背景色为黑色）
    //SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
}

//获取当前函数的行号。其实不一定是行数名称的开始行，大部分其实是从块号开始。
//funNameOrBlock 0 从函数名开始 1 从块号开始
int getLastFunStartLineNum(int funNameOrBlock)
{
    if(s_sysNode == nullptr){
        return 0;
    }

    int lastCallBackFunOffset = 0;

    for (int i = s_sysNode->size() - 1; i >= 0; --i)
    {
        SymNode* v = s_sysNode->at(i);

        /* 应该不需要了，现在回调已经不是转义执行，而是直接执行。20250304
        //前面有一个hd回调函数，此时要加上回调函数自身在函数中的偏移行数。因为回调函数是使用转义后直接调用函数的具体函数
        //如果是在回调函数中，则要加上回调偏移。
        if(v->type == HD_TO_HS_INFO && lastCallBackFunOffset == 0)
        {
            size_t pos = v->name.find('@');
            if (pos != std::string::npos) {
                std::string linenum = v->name.substr(0, pos);
                lastCallBackFunOffset = std::stoi(linenum) - 1;
            }
        }*/

        //已经到第一从作用域，设置后返回
        if (v->type == FUN_SYM)
        {
            FUN_SYM_INFO* pSym = findFunBlock(v->name);
            if(pSym != nullptr)
            {
                return ((funNameOrBlock == 0)?pSym->funNameLineNum: pSym->blockLineNum) + lastCallBackFunOffset;
            }
        }
    }
    return 0;
}

//获取原始的完整语句
QString getSrcCodeState(antlr4::ParserRuleContext* ctx)
{
    antlr4::misc::Interval interval = ctx->getSourceInterval();

    // 从 TokenStream 提取文本
    std::string srcCode = tokensListen->getText(interval);

    return QString::fromStdString(srcCode);
}

//获取原始的完整语句,只获取一行。多余的不要。
QString getSrcCodeStateOneline(antlr4::ParserRuleContext* ctx)
{

    int  startIndex = ctx->getStart()->getTokenIndex();

    int stopIndex = startIndex;

    int line = ctx->getStart()->getLine();

    while (stopIndex < tokensListen->size() && (tokensListen->get(stopIndex)->getLine() < (line+1))) {
        ++stopIndex;
    }
    stopIndex--;

    if (startIndex >= 0 && startIndex <= stopIndex)
    {
        // 获取出错行的文本
        std::string oneLineText = tokensListen->getText(antlr4::misc::Interval((size_t)startIndex, (size_t)stopIndex));
        return QString::fromStdString(oneLineText);
    }

    // 从 TokenStream 提取文本
    antlr4::misc::Interval interval = ctx->getSourceInterval();
    std::string srcCode = tokensListen->getText(interval);

    return QString::fromStdString(srcCode);
}

int getCurLineNum(antlr4::ParserRuleContext* ctx)
{

    //最后出错时，函数的开始位置。这里其实要从块号开始，比较调用函数不是从函数名，而是真正从块开始计算的。
    //int offsetline = getLastFunStartLineNum(1);

    if(ctx->getStart() != nullptr)
    {
         //这个ctx->getStart()->getLine()也很关键，最后出错时，在具体函数中的偏移位置。
        //得保存起来一下，后面打印详细栈需要这个行号。这个偏移是从块号开始计数的。
        pin_status_info info;
        info.status = LAST_ERROR_LINE_NUM;
        info.data = ctx->getStart()->getLine();
        pushStatus(info);

        return /*offsetline + */info.data;
    }


    return -1;
}

int getGloblCurlineNum(antlr4::ParserRuleContext* ctx)
{
    int linenum = ctx->getStart()->getLine();
    FUN_SYM_INFO* pGlobal = findFunBlock("quanju_dingyi");
    if(pGlobal != nullptr)
    {
        linenum += pGlobal->funNameLineNum - 1;//因为全局是个特例，其第1行是从quanju_dingyi本身开始的。
    }
    return linenum;
}

//手动删除一个变量节点，当前是在HD_TO_HS_INFO 中使用
void deleteCurScopeVar(SymNode* pSym)
{
    for (int i = s_sysNode->size() - 1; i >= 0; --i)
    {
        SymNode* v = s_sysNode->at(i);

        if(v == pSym)
        {
            v->destory();
            s_sysNode->takeAt(i);
            delete v;
#ifdef PIN_MEM_REF
            freeTimes++;
#endif
            break;
        }
    }
}

//在多级函数的调用中，错误后会自动调用这个函数，来对ctx进行替换，如此让报错更加精确。
int getCurLineNum(PinParser::RealCallFunContext* & ctx)
{
    if(s_sysNode == nullptr)
    {
        return 0;
    }

    int curOffSetLineNum = 0;

    if (ctx->getStart() != nullptr)
    {
        //这个ctx->getStart()->getLine()也很关键，最后出错时，在具体函数中的偏移位置。
        //得保存起来一下，后面打印详细栈需要这个行号。这个偏移是从块号开始计数的。
        pin_status_info info;
        info.status = LAST_ERROR_LINE_NUM;
        info.data = ctx->getStart()->getLine();
        pushStatus(info);

        curOffSetLineNum = info.data;

        return curOffSetLineNum;
    }

#if 0
    //int callbackOffsetLine = 0;
    //检查是否有多函数调用，如果有，要替换ctx
    for (int i = s_sysNode->size() - 1; i >= 0; --i)
    {
        SymNode* v = s_sysNode->at(i);

        if (v->type == EXPR_MULTI_FUN_CALL_CTX)
        {

            ctx = (PinParser::RealCallFunContext*)v->value.vpoint;
            break;
        }

        //如果有回调函数，则要加上其偏移量
        /*if(v->type == HD_TO_HS_INFO)
        {
            callbackOffsetLine = v->
        }*/
        //已经到第一从作用域，设置后返回
        if (v->type == FUN_SYM)
        {
            break;
        }
    }
#endif

    /*
    int offsetline = getLastFunStartLineNum(1);

    //现在直接调用函数，不是读取语句后转移。不需要加函数基地址了
    if(ctx->getStart() != nullptr)
    {
        return offsetline + curOffSetLineNum;
    }*/

    return -1;
}



//检查文件的头部，是否有编码BOM
CODE_ID DetectFileHeadBomEncode(const uchar* pBuffer, int length, int& skip)
{
    if (length < 3)
    {
        return UNKOWN;
    }
    if (pBuffer[0] == 0xFF && pBuffer[1] == 0xFE)
    {
        skip = 2;
        return CODE_ID::UNICODE_LE; //skip 2
    }
    if (pBuffer[0] == 0xFE && pBuffer[1] == 0xFF)
    {
        skip = 2;
        return CODE_ID::UNICODE_BE; //skip 2
    }
    if (pBuffer[0] == 0xEF && pBuffer[1] == 0xBB && pBuffer[2] == 0xBF)
    {
        skip = 3;
        return CODE_ID::UTF8_BOM; //skip 3 with BOM
    }

    return UNKOWN;
}

//outUtf8Code 如果可以，输出正确的utf8编码
int checkCodeTextEncode(const uchar* pText, int length, QByteArray& outUtf8Code)
{
    int skip = 0;
    CODE_ID headCode = DetectFileHeadBomEncode(pText, length, skip);

    //是utf8bom，则进行检查是否是合法的uft8。
    if (headCode == CODE_ID::UTF8_BOM || headCode == CODE_ID::UNICODE_LE || headCode == CODE_ID::UNICODE_BE)
    {
        QByteArray firstCode = getQtCodecNameById(headCode);

        QTextCodec::ConverterState state;
        QTextCodec* codec = QTextCodec::codecForName(firstCode.data());
        const QString text = codec->toUnicode((const char*)pText + skip, length, &state);
        if (state.invalidChars == 0) {

            outUtf8Code = text.toUtf8();
            return 2;
        }
        else
        {
            QString errmsg = QString(u8"源代码中存在非法的未知编码字符，请检查源代码文件，删除错误的编码字符后再运行！");
            AbortException(errmsg);
        }
    }

    //不是以上几种编码，则再检查utf8 和 gbk

    QTextCodec::ConverterState state;
    QTextCodec* codec = QTextCodec::codecForName("UTF-8");
    const QString text = codec->toUnicode((const char*)pText, length, &state);

    //不是合法的utf8编码。再检查是不是gbk
    if (state.invalidChars > 0) {

        QTextCodec::ConverterState state1;

        QTextCodec* codec1 = QTextCodec::codecForName("GB18030");
        QString out = codec1->toUnicode((const char*)pText, length, &state1);
        if (state1.invalidChars > 0) {
            //也不是gbk
            QString errmsg = QString(u8"源代码不是GBK或UTF8编码，存在非法的未知编码字符，请检查源代码文件，删除错误的编码字符后再运行！");
            AbortException(errmsg);
            return -1;//不是utf8,也不是gbk
        }
        else
        {
            //是合法的gbk编码，转换为utf8即可。
            outUtf8Code = out.toUtf8();
            return 1;
        }
    }

    outUtf8Code = QByteArray((char*)pText, length);
    return 0; //是合法的gbk编码。

}

//与getCodeNameById类似，但是返回的是QT系统支持的编码的字符串名称
QByteArray getQtCodecNameById(int id)
{
    QByteArray ret;

    switch (id)
    {
    case UNKOWN:
    case ANSI:
        ret = "unknown";
        break;
    case UNICODE_LE:
        ret = "UTF16-LE";
        break;
    case UNICODE_BE:
        ret = "UTF16-BE";
        break;
    case UTF8_NOBOM://qt没有这种
    case UTF8_BOM:
        ret = "UTF-8";
        break;
    case GBK:
        ret = "GB18030";
        break;
    case EUC_JP:
        ret = "EUC-JP";
        break;
    case Shift_JIS:
        ret = "Shift-JIS";
        break;
    case EUC_KR:
        ret = "EUC-KR";
        break;
    case KOI8_R:
        ret = "KOI8-R";
        break;
    case TSCII:
        ret = "TSCII";
        break;
    case TIS_620:
        ret = "TIS-620";
        break;
    case BIG5:
        ret = "Big5-HKSCS";
        break;
    case WINDOWS1250:
        ret = "UTF-8"; //暂时不支持windows-1250。发现此时往往是发生了错误。直接使用utf8 而非"windows-1250";
        break;
    case IBM866:
        ret = "IBM866"; //qt不支持ibm865,干脆865 866都按照866支持
        break;
    default:
        ret = "UTF-8";
        break;
    }

    return ret;
}
